package eva.savant.business.ventas.view

import eva.savant.business.ventas.service.TSVenta
import eva.savant.businessobject.cg.Cajero
import eva.savant.businessobject.cg.Credito
import eva.savant.businessobject.gl.Nit
import eva.savant.businessobject.mt.*
import eva.savant.businessobject.vt.*
import org.primefaces.event.SelectEvent

public class TVenta extends Bean {

  String report, barcode

  Boolean nota= true

  Boolean credito

  String nit, razon

  def XMaterialCod =''

  VentaDetalle detalle

  Almacenero almacenero

  Almacen almacen

  Cajero cajero

  TSVenta tsVenta

  Dosificacion dosificacion

  Date dateIni, dateEnd

  public void clean(Cajero ca, Almacen a, Almacenero o, Dosificacion d, Cliente c) {

    dateIni= dateEnd= new Date()

    focus= 'ps:materialId:valueId'

    //report= barcode= null

    //nota= credito= true

    nit= razon= null

    cajero= ca

    almacen= a

    almacenero= o

    dosificacion= d

    def f= entity != null? entity.fecha : new Date()


    entity= new Venta(); init()

    entity.fecha= f

    entity.cliente= c

    entity.lsVentaDetalle= new ArrayList<VentaDetalle>()

    entity.vendedor= get(Vendedor,'persona.id=?',usuario.persona.id)


    XMaterialCod= null

    detalle= new VentaDetalle()

    detalle.material= new Material()


    tsVenta= (TSVenta) getSpringBean('tsVenta')


    if(entity.vendedor == null) addErrorMessage 'El usuario actual no es vendedor'       //verificar  vend alma

    if(almacen?.id == null) addErrorMessage 'Debe seleccionar un almacen para la venta'
  }

  public List findLsEntity() {

    dateIni= toStartDay(dateIni); dateEnd= toMidnight(dateEnd);

    return find(Pedido,'estado=? and fecha between ? and ? order by fecha, id, glosa', 'P', dateIni, dateEnd)
  }

  public void editEntity(Object id) {

    def pedido= get(Pedido,id)


    entity= new Venta()

    entity.pedido= pedido

    entity.fecha= pedido.fecha

    entity.cliente= pedido.cliente

    entity.lsVentaDetalle= new ArrayList<VentaDetalle>()

    entity.vendedor= get(Vendedor,'persona.id=?',usuario.persona.id)


    for(x in pedido.lsPedidoDetalle) {

    def p= get(Precio,'canal.id=? and material.id=?',pedido.cliente.canal.id,x.material.id)

    def i= get(Inventario,'almacen.id=? and material.id=?',almacen.id,x.material.id)


    def d= new VentaDetalle()

    d.material = x.material

    d.cantidad = x.cantidad


    d.precio   = p?.precio    > 0? p.precio    : 0

    d.impuesto = p?.impuesto  > 0? p.impuesto  : 0

    d.descuento= p?.descuento > 0? p.descuento : 0


    d.importe  = d.cantidad * d.precio

    d.impuesto = d.cantidad * d.impuesto

    d.descuento= d.cantidad * d.descuento

    d.total    = (d.importe - d.descuento) + d.impuesto

    d.stock    = i != null ? i.actual : null


    entity.lsVentaDetalle.add d }


    nit= entity.cliente.nit

    razon= entity.cliente.razon

    calculateSummary()


    credito= get(Credito,'persona.id=?',entity.cliente.persona.id).condpago.valor > 0
  }

  public void XMaterialFind() {

    detalle.material= get(Material,'rapido=?',toInteger(XMaterialCod))

    if(detalle.material == null) detalle.material= get(Material, sociedad.id + XMaterialCod)

    if(detalle.material == null) detalle.material= get(Material,'barras=?', XMaterialCod)

    if(detalle.material != null) XMaterialSelect() else focus= 'hd:nitId:valueId'
  }

  public void XMaterialSelect() {

    focus= 'ps:cantidadId:valueId'

    XMaterialCod= detalle.material.codigo


    def i= get(Inventario,'almacen.id=? and material.id=?',almacen.id,detalle.material.id)

    if(i == null)

    addErrorMessage 'El almacen ' + almacen.codigo + ' no tiene el material ' + detalle.material.codigo


    def p= get(Precio,'canal.id=? and material.id=?',entity.cliente.canal.id,detalle.material.id)

    detalle.precio   = p?.precio    > 0? p.precio    : 0

    detalle.impuesto = p?.impuesto  > 0? p.impuesto  : 0

    detalle.descuento= p?.descuento > 0? p.descuento : 0

    detalle.stock    = i != null ? i.actual : null

    if(p == null)

    addErrorMessage 'El canal ' + entity.cliente.canal.codigo + ' no tiene el material ' + detalle.material.codigo
  }

  public void detailAdd() {

    if(!(detalle.precio > 0)) { addErrorMessage 'El precio del producto debe ser mayor a cero'; return; }


    if(detalle.cantidad < 1) { addErrorMessage 'La cantidad de producto debe ser mayor a cero'; return; }


    if(detalle.cantidad > detalle.stock  && almacen.stock == 1) {

    addErrorMessage'Cantidad solicitado es mayor al saldo disponible del material ' + detalle.material.codigo; return }


    def d= new VentaDetalle()

    d.material = detalle.material

    d.cantidad = detalle.cantidad

    d.precio   = detalle.precio

    d.importe  = detalle.cantidad * detalle.precio

    d.impuesto = detalle.cantidad * detalle.impuesto

    d.descuento= detalle.cantidad * detalle.descuento

    d.total    = (d.importe - d.descuento) + d.impuesto

    d.stock    = detalle.stock


    detailDelete(d); entity.lsVentaDetalle.add(d); calculateSummary()


    detalle= new VentaDetalle()

    detalle.material= new Material()

    XMaterialCod= ''

    focus= 'ps:materialId:valueId'
  }

  public boolean mergeEntity(Object entity) { alta(entity); entity= (Venta) entity

    if(credito) entity.pagado= entity.total; entity.tipo= credito? 'C' : 'E'

    if(entity.lsVentaDetalle?.size() < 1) { addErrorMessage 'El detalle de productos esta vacio'; return false }

    if(entity.pagado < entity.total) { addErrorMessage 'El monto pagado es menor al monto total'; return false }


    if(nota) { entity.tipo= entity.tipo + 'N'

    entity = tsVenta.saveVenta(cajero, almacen, almacenero, entity)

    addInfoMessage 'La NOTA DE VENTA fue registrada con el codigo ' + entity.id

    report= reportService.reportToTXT('notaVenta',['ventaId':entity.id,'moneda':'Bolivianos'])

    report= report.replaceAll("\n","\\|")

    } else { entity.tipo= entity.tipo + 'F'

    def libroventas = tsVenta.saveVenta(cajero, almacen, almacenero, dosificacion, entity, nit, razon)

    addInfoMessage 'La venta fue registrada con la FACTURA ' + libroventas?.factura; buildReportFactura(libroventas) }


    println 'Reporte: \n' + report + '\n' + barcode; return entity != null
  }

  public void buildReportFactura(Libroventas l) {

    report= reportService.reportToTXT('factura',['libroventasId':l?.id])

    def ini= report.indexOf('['), end= report.indexOf(']')

    def code= report.substring(ini+1,end)

    barcode= code.replaceAll(' ','').replaceAll('\n','')

    report= report.substring(0,ini)
  }

  public void cleanPrint() {

    report= barcode= null; nota= true
  }

  public void detailEdit(SelectEvent event) {

    if(isRead) return

    def x            = (VentaDetalle) event.object

    detalle          = new VentaDetalle()

    detalle.material = x.material

    detalle.cantidad = x.cantidad

    detalle.precio   = x.precio

    detalle.impuesto = x.impuesto

    detalle.descuento= x.descuento

    detalle.importe  = x.importe

    detalle.total    = x.total

    XMaterialCod     = x.material.codigo
  }

  public void detailDelete(VentaDetalle detalle) {

    for(int i=0; i < entity.lsVentaDetalle.size(); i++)  { def d= entity.lsVentaDetalle.get(i)

    if(d.material.id.equalsIgnoreCase(detalle.material.id)) { entity.lsVentaDetalle.remove(i); break } }

    calculateSummary()
  }

  public void calculateSummary() {

    entity.importe   = 0

    entity.impuesto  = 0

    entity.descuento = 0

    entity.total     = 0

    entity.pagado    = 0

    entity.vuelto    = 0


    for(detalle in entity.lsVentaDetalle) {

    entity.importe   = entity.importe   + detalle.importe

    entity.impuesto  = entity.impuesto  + detalle.impuesto

    entity.descuento = entity.descuento + detalle.descuento

    entity.total     = entity.total     + detalle.total  }
  }

  public void calVuelto() { entity.vuelto= entity.pagado - entity.total; }

  public void buscarNIT() { def n= get(Nit, nit); if(n != null) razon= n.razon; focus= 'hd:nombreId:input' }

  public void selectCliente() { nit= entity.cliente.nit; razon= entity.cliente.razon

                                credito= get(Credito,'persona.id=?',entity.cliente.persona.id).condpago.valor > 0 }

  def getXMaterialConverter() { return converterLike(Material) }

  def XMaterialComplete(String value) { return completeLike(Material,'nombre',value) }

}
